#include <stdio.h>
#include <termios.h>
#include <unistd.h>
#include <strings.h>

#include "../include/uart.h"

/**
*@brief   设置串口数据位，停止位和效验位
*@param  fd     类型  int  打开的串口文件句柄
*@param  databits 类型  int 数据位   取值 为 7 或者8
*@param  stopbits 类型  int 停止位   取值为 1 或者2
*@param  parity  类型  int  效验类型 取值为N,E,O,,S
*/
int set_Parity(int fd, int databits, int stopbits, int parity)
{
	struct termios options;
	if (tcgetattr(fd, &options) != 0)
	{
		perror("SetupSerial 1");
		return -1;
	}

	options.c_cflag &= ~CSIZE;

	switch (databits) /*设置数据位数*/
	{
	case 7:
		options.c_cflag |= CS7;
		break;
	case 8:
		options.c_cflag |= CS8;
		break;
	default:
		fprintf(stderr, "Unsupported data size\n");
		return -1;
	}
	switch (parity)
	{
	case 'n':
	case 'N':
		options.c_cflag &= ~PARENB; /* Clear parity enable */
		options.c_iflag &= ~INPCK;	/* Enable parity checking */
		break;
	case 'o':
	case 'O':
		options.c_cflag |= (PARODD | PARENB); /* 设置为奇效验*/
		options.c_iflag |= INPCK;			  /* Disnable parity checking */
		break;
	case 'e':
	case 'E':
		options.c_cflag |= PARENB;	/* Enable parity */
		options.c_cflag &= ~PARODD; /* 转换为偶效验*/
		options.c_iflag |= INPCK;	/* Disnable parity checking */
		break;
	case 'S':
	case 's': /*as no parity*/
		options.c_cflag &= ~PARENB;
		options.c_cflag &= ~CSTOPB;
		break;
	default:
		fprintf(stderr, "Unsupported parity\n");
		return -1;
	}

	/* 设置停止位*/
	switch (stopbits)
	{
	case 1:
		options.c_cflag &= ~CSTOPB;
		break;
	case 2:
		options.c_cflag |= CSTOPB;
		break;
	default:
		fprintf(stderr, "Unsupported stop bits\n");
		return -1;
	}

	/* Set input parity option */
	if (parity != 'n')
		options.c_iflag |= INPCK;
	tcflush(fd, TCIFLUSH);
	options.c_cc[VTIME] = 150; /* 设置超时15 seconds*/
	options.c_cc[VMIN] = 0;	   /* Update the options and do it NOW */

	options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); /*Input*/
	options.c_oflag &= ~OPOST;							/*Output*/
	if (tcsetattr(fd, TCSANOW, &options) != 0)
	{
		perror("SetupSerial 3");
		return -1;
	}
	return 0;
}

/**
*@brief   设置串口数据位，停止位和效验位
*@param  fd			类型	int		打开的串口文件句柄
*@param  baudrate	类型	speed_t	波特率		
	取值	 实际值
	B115200  00021
	B230400  00022
	B460800  00023
	B500000  00024
	B576000  00025
	B921600  00026
	B1000000 00027
	B1152000 00030
	B1500000 00031
	B2000000 00032
	B2500000 00033
	B3000000 00034
	B3500000 00035
	B4000000 00036
*@param  databits	类型	int		数据位		取值为 7 或者8
*@param  stopbits	类型	int		停止位		取值为 1 或者2
*@param  parity		类型	int		效验类型	取值为N,E,O,,S
*/
int init_uart(int fd, speed_t baudrate, int databit, int stopbit, int parity)
{
	struct termios opt;
	bzero(&opt, sizeof(struct termios));
	tcgetattr(fd, &opt);
	cfsetspeed(&opt, B115200);
	tcsetattr(fd, TCSANOW, &opt);
	tcflush(fd, TCIOFLUSH);

	if (set_Parity(fd, databit, stopbit, parity) < 0)
	{
		fprintf(stderr, "Set Parity Error\n");
		return -1;
	}
	tcflush(fd, TCIOFLUSH);
	return 0;
}